/*
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *      
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *      
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */

#ifndef _SYNTAX_H
#define _SYNTAX_H

#include <iostream>
#include <sstream>
#include <string>
#include <cstdlib>

#include "gType.h"
#include "lexical.h"
#include "sematic.h"


#define ERROR_SYMBOL 		"An invalid symbol."
#define ERROR_COORDINATES 	"Point's coordinates was not found."
#define ERROR_CIRCLE		"Middle coordinates of a circle was not typed."
#define ERROR_PARAM 		"An invalid parameter."
#define ERROR_OBJECT		"An object isn't enclosed."
#define ERROR_RADIUS		"Circle coordinates don't make sence."
#define ERROR_NAME		"Names of the objects must be different."
#define ERROR_VOID		"A content between the object tag is empty."


class syntax{
	
	public:
		static const float initialFeed = 0.0;
		static const int initialSpindle = -1;
		static const float initialX = 0.0;
		static const float initialY = 0.0;
		static const float initialZ = 0.0;
		
		class parseError: public lexical::invalidToken{
		
			private:
			std::string report;
				
			public:
				parseError(unsigned, const char *) throw();
				virtual ~parseError() throw();
				
				virtual const char *what() const throw();
		
		};
	
	private:
	
		lexical *lexicalAnalysis;
		float feed;
		int spindle;
		float xyzCoordinates[3];
		bool relative;
		std::string objectName;
		
		lexical::token &getToken(lexical::token &)
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		lexical::token &nonCoordinates(gObject &, lexical::token &) 
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		lexical::token &nonControl(gObject &, lexical::token &) 
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		lexical::token &nonParam(lexical::token &) 
			throw(reader::bufferOverflow, std::ifstream::failure);
		lexical::token &nonLinear(gObject &, lexical::token &) 
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		lexical::token &nonArc(gObject &, lexical::token &) 
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		lexical::token &nonRadius(gObject &, lexical::token &) 
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		lexical::token &nonOptions(gObject &, lexical::token &)
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		bool evalRadius(gObject &, float);
			
	public:
		syntax(lexical *);
		
		gObjectContainer &getContainer(gObjectContainer &)
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);
		gObject &getAllCoords(gObject &)
			throw(reader::bufferOverflow, std::ifstream::failure, parseError);

};

#endif
